package com.test.config;

import com.test.bean.Car;
import com.test.bean.Color;
import com.test.dao.BookDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/11/29 9:31
 * <p>
 * 自定义装配：Spring利用依赖注入（DI），完成对IOC容器中各个组件的依赖关系赋值
 * 1）@Autowired：自动注入
 * 1.1 默认优先按照类型去容器中找对应的组件的id去容器中查找
 * 1.2 如果找到多个相同类型的组件，再将属性的名称作为组件的id去
 * 1.3 @Qualifier("bookDao1"),使用@Qualifier指定需要装配的组件的id，而不是使用属性名
 * 1.4 默认一定要将属性赋值好，否则没有就会报错;可以使用@Autowire中的required属性进行调整
 * 1.5 @Primary，让Spring进行自动装配的时候，默认使用首选的bean
 * 也可以继续使用@Qualifier指定需要装配的bean的名字
 * <p>
 * 2）Spring还支持使用@Resource（JSR250）和@Inject(JSR330)[Java规范的注解]
 * @Resource: 可以和@Autowired一样实现自动装配功能，默认是按照组件名称进行装配的
 * 没有能支持@Primary功能，也没有支持@Autowired（required=false）;
 * @Inject: 需要导入javax.inject依赖包, 和@Autowired的功能一样，没有required=false的功能
 * @Autowire 是Spring定义的，@Resource和@Inject都是java规范
 * 推荐使用@Autowire注解
 * AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能
 * <p>
 * 3.@Autowire：构造器，参数，方法，属性，都是从容器中获取组件的值
 * 3.1 [标注在方法位置],@Bean + 方法参数，参数从容器中获取；默认不写@Autowired效果是一样的，都能自动装配
 * 3.2 [标注在构造器上]，如果组件只有一个有参构造器，这个有参构造器的@Autowire可以省略，参数位置的组件还是可以自动从容器中获取
 * 3.3 标注在参数位置
 * <p>
 * 4.自定义组件想要使用Spring容器底层的一些组件（Application，BeanFactory， xxx）
 * 自定义组件需要实现xxxAware接口，在创建对象的时候会调用接口规定的方法，注入相关的组件.
 * 把spring底层的一些组件注入到自定义的bean中
 * xxxAware的功能使用xxxProcessor方法处理，每一个xxxAware都有对应的后置处理器进行处理
 */
@Configuration
@ComponentScan({"com.test.controller", "com.test.dao", "com.test.service", "com.test.bean"})
public class MainConfigAutowire {

    @Primary
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao = new BookDao();
        bookDao.setLabel("2");
        return bookDao;
    }

    /**
     * @param car
     * @return
     * @Bean 标注的方法创建对象的时候，方法参数的值从容器中获取
     */
    @Bean
    public Color color(Car car) {
        Color color = new Color();
        color.setCar(car);
        return color;
    }
}
